TRATAMENTO DE DADOS NO PYTHON - PARTE 2
Formatos Long e Wide
1 Tabelas de dados podem ser organizadas de diversas maneiras, conforme a necessidade, contexto ou, até mesmo, as preferências individuais do usuário. No entanto, para padronizar a organização de dados em tabelas e evitar situações caóticas, existem alguns princípios que devem ser seguidos para facilitar a interpretação e a manipulação de dados tabulares:
- Cada variável tem sua própria coluna
- Cada observação tem sua própria linha
- Cada valor tem sua própria célula
Existem dois tipos de transformações (opostas) em tabelas, que são úteis para organizá-las de modo a seguir (ou não) os 3 princípios destacados:
pivot(): faz a tabela ser mais “longa” ao aumentar o nº de linhas e diminuir o nº de colunas.melt(): faz a tabela ser mais “larga” ao diminuir o nº de linhas e aumentar o nº de colunas.
Exemplo de transformação long:
Exemplo de transformação wide:
Dados de exemplo
# Importar bibliotecas
import pandas as pd
import janitor
# Dados do IPCA (Sidra/IBGE)
dados_sidra = pd.read_json(
path_or_buf = "https://apisidra.ibge.gov.br/values/t/7060/n1/all/v/all/p/all/c315/7169/d/v63%202,v66%204,v69%202,v2265%202?formato=json"
)
# Dados de expectativas de inflação (Focus/BCB)
dados_focus = pd.read_csv(
filepath_or_buffer = "https://olinda.bcb.gov.br/olinda/servico/Expectativas/versao/v1/odata/ExpectativasMercadoAnuais?%24filter=%28Indicador%20eq%20%27IPCA%27%20or%20Indicador%20eq%20%27IGP-M%27%29%20and%20Data%20ge%20%272021-01-01%27%20and%20Data%20le%20%272024-04-12%27&%24format=text/csv&%24orderby=Data%20desc",
decimal = ","
)Para exemplificar essas transformações, tem-se a tabela de dados do IPCA, extraida do Sidra/IBGE, que vem com as variáveis (var. mensal, acumulada, peso, etc.) empilhadas em uma única coluna, quebrando o primeiro princípio:
tabela = (
dados_sidra
.rename(columns = {"V": "valor", "D3C": "mes", "D2N": "variavel"})
.query("valor != 'Valor'")
.filter(items = ["mes", "variavel", "valor"])
)
tabela mes variavel valor
1 202001 IPCA - Variação mensal 0.21
2 202002 IPCA - Variação mensal 0.25
3 202003 IPCA - Variação mensal 0.07
4 202004 IPCA - Variação mensal -0.31
5 202005 IPCA - Variação mensal -0.38
.. ... ... ...
204 202312 IPCA - Peso mensal 100.0000
205 202401 IPCA - Peso mensal 100.0000
206 202402 IPCA - Peso mensal 100.0000
207 202403 IPCA - Peso mensal 100.0000
208 202404 IPCA - Peso mensal 100.0000
[208 rows x 3 columns]
Para organizar essa tabela, conforme os 3 princípios, deve-se aplicar uma transformação de modo que resulte em uma coluna para cada uma das 4 variáveis que estão, atualmente, empilhadas. Ou seja, o objetivo é diminuir o nº de linhas e aumentar o nº de colunas. Isso pode ser feito com a função pivot():
# Formato wide: para quando é necessário colocar cada variável em uma coluna
tabela.pivot(
index = "mes", # coluna que unicamente identifica as observações
columns = "variavel", # coluna onde os nomes das variáveis estão
values = "valor" # coluna onde os valores das células estão
)variavel IPCA - Peso mensal ... IPCA - Variação mensal
mes ...
202001 100.0000 ... 0.21
202002 100.0000 ... 0.25
202003 100.0000 ... 0.07
202004 100.0000 ... -0.31
202005 100.0000 ... -0.38
202006 100.0000 ... 0.26
202007 100.0000 ... 0.36
202008 100.0000 ... 0.24
202009 100.0000 ... 0.64
202010 100.0000 ... 0.86
202011 100.0000 ... 0.89
202012 100.0000 ... 1.35
202101 100.0000 ... 0.25
202102 100.0000 ... 0.86
202103 100.0000 ... 0.93
202104 100.0000 ... 0.31
202105 100.0000 ... 0.83
202106 100.0000 ... 0.53
202107 100.0000 ... 0.96
202108 100.0000 ... 0.87
202109 100.0000 ... 1.16
202110 100.0000 ... 1.25
202111 100.0000 ... 0.95
202112 100.0000 ... 0.73
202201 100.0000 ... 0.54
202202 100.0000 ... 1.01
202203 100.0000 ... 1.62
202204 100.0000 ... 1.06
202205 100.0000 ... 0.47
202206 100.0000 ... 0.67
202207 100.0000 ... -0.68
202208 100.0000 ... -0.36
202209 100.0000 ... -0.29
202210 100.0000 ... 0.59
202211 100.0000 ... 0.41
202212 100.0000 ... 0.62
202301 100.0000 ... 0.53
202302 100.0000 ... 0.84
202303 100.0000 ... 0.71
202304 100.0000 ... 0.61
202305 100.0000 ... 0.23
202306 100.0000 ... -0.08
202307 100.0000 ... 0.12
202308 100.0000 ... 0.23
202309 100.0000 ... 0.26
202310 100.0000 ... 0.24
202311 100.0000 ... 0.28
202312 100.0000 ... 0.56
202401 100.0000 ... 0.42
202402 100.0000 ... 0.83
202403 100.0000 ... 0.16
202404 100.0000 ... 0.38
[52 rows x 4 columns]
Um exemplo inverso pode ser visto com os dados de expectativas do Focus. Após alguns tratamentos, muda-se a organização da tabela para simular o problema de ter mais de uma observação nas linhas (isso é menos frequente, mas acontece). Observe:
# Dados de exemplo 2: expectativas Focus para o IPCA
dados = (
dados_focus
.query("Indicador == 'IPCA' and DataReferencia in [2024, 2025] and baseCalculo == 0")
.filter(items = ["Data", "DataReferencia", "Mediana"], axis = "columns")
.pivot(index = "Data", columns = "DataReferencia", values = "Mediana")
.reset_index()
)
dadosDataReferencia Data 2024 2025
0 2021-01-04 3.2000 NaN
1 2021-01-05 3.2000 NaN
2 2021-01-06 3.2000 NaN
3 2021-01-07 3.2000 NaN
4 2021-01-08 3.2400 NaN
.. ... ... ...
817 2024-04-08 3.7510 3.5256
818 2024-04-09 3.7510 3.5287
819 2024-04-10 3.7000 3.5287
820 2024-04-11 3.7000 3.5287
821 2024-04-12 3.7093 3.5561
[822 rows x 3 columns]
dadosDataReferencia Data 2024 2025
0 2021-01-04 3.2000 NaN
1 2021-01-05 3.2000 NaN
2 2021-01-06 3.2000 NaN
3 2021-01-07 3.2000 NaN
4 2021-01-08 3.2400 NaN
.. ... ... ...
817 2024-04-08 3.7510 3.5256
818 2024-04-09 3.7510 3.5287
819 2024-04-10 3.7000 3.5287
820 2024-04-11 3.7000 3.5287
821 2024-04-12 3.7093 3.5561
[822 rows x 3 columns]
Note que os nomes de colunas 2024 e 2025 são, na verdade, valores de uma variável que se refere ao horizonte de expectativas (DataReferencia); e os valores nestas colunas representam os valores da variável Mediana, uma das estatísticas do Focus.
Assim, tem-se o problema de mais de uma observação por linha, de modo que para organizar a tabela, deve-se aplicar uma transformação que diminua o nº de colunas e aumente o nº de linhas. A função melt() faz isso:
# Formato long: para quando cada linha representa mais de uma observação
dados.melt(
id_vars = ["Data"], # colunas que identificam as observações
value_vars = [2024, 2025], # colunas para transformar pro formato longo
var_name = "data_ref", # nome da coluna que armazenará os nomes de [2024, 2025]
value_name = "mediana" # nome da coluna que armazenará os valores de [2024, 2025]
) Data data_ref mediana
0 2021-01-04 2024 3.2000
1 2021-01-05 2024 3.2000
2 2021-01-06 2024 3.2000
3 2021-01-07 2024 3.2000
4 2021-01-08 2024 3.2400
... ... ... ...
1639 2024-04-08 2025 3.5256
1640 2024-04-09 2025 3.5287
1641 2024-04-10 2025 3.5287
1642 2024-04-11 2025 3.5287
1643 2024-04-12 2025 3.5561
[1644 rows x 3 columns]
Cruzamento de Dados
Um cruzamento é uma maneira de conectar cada linha em X a zero, uma ou mais linhas em Y. O diagrama a seguir mostra as correspondências pelas “chaves” indicadas como pontos. O número de pontos é o número de correspondências e, ao mesmo tempo, é o número de linhas na tabela resultante.
Este é o tipo mais simples de cruzamento, chamado de inner join. Esse cruzamento retorna pares de observações somente para quando as chaves das tabelas corresponderem. Ou seja, as linhas sem correspondência não são incluídas no resultado final.
Um inner join mantém as observações que aparecem em ambas as tabelas. Um outer join mantém as observações que aparecem em pelo menos uma das tabelas. Existem três tipos de outer joins:
- left join mantém todas as observações em
x. - right join mantém todas as observações em
y. - full join mantém todas as observações em
xey.
De forma ilustrada, estes cruzamentos podem ser representados assim:
Dados de exemplo
# Importar bibliotecas
import pandas as pd
import ipeadatapy as ipea
from bcb import sgs
# Dados do saldo do CAGED (Ipeadata)
dados_ipeadata = ipea.timeseries("CAGED12_SALDON12")
# Dados do IDP/BP - acum. 12m - US$ (milhões) (SGS/BCB)
dados_sgs = sgs.get(codes = {"idp": 24422},
start = "2019-11-01",
end = "2024-03-01")Cruzamento inner join
Para verificar como o inner join funciona, primeiro cria-se duas tabelas para as séries temporais do CAGED e do IDP, ou seja, a “chave” será a coluna data:
# Dados de exemplo:
tabela_caged = (
dados_ipeadata
.reset_index()
.rename(columns = {"DATE": "data", "VALUE (Pessoa)": "caged"})
# .filter(items = ["data", "caged"], axis = "columns").query("data <= '2020-06-01'")
.set_index("data")
)
tabela_caged CODE RAW DATE ... YEAR caged
data ...
2020-01-01 CAGED12_SALDON12 2020-01-01T00:00:00-03:00 ... 2020 92678.0
2020-02-01 CAGED12_SALDON12 2020-02-01T00:00:00-03:00 ... 2020 198368.0
2020-03-01 CAGED12_SALDON12 2020-03-01T00:00:00-03:00 ... 2020 -232316.0
2020-04-01 CAGED12_SALDON12 2020-04-01T00:00:00-03:00 ... 2020 -902317.0
2020-05-01 CAGED12_SALDON12 2020-05-01T00:00:00-03:00 ... 2020 -352790.0
2020-06-01 CAGED12_SALDON12 2020-06-01T00:00:00-03:00 ... 2020 -23111.0
2020-07-01 CAGED12_SALDON12 2020-07-01T00:00:00-03:00 ... 2020 123297.0
2020-08-01 CAGED12_SALDON12 2020-08-01T00:00:00-03:00 ... 2020 238125.0
2020-09-01 CAGED12_SALDON12 2020-09-01T00:00:00-03:00 ... 2020 313564.0
2020-10-01 CAGED12_SALDON12 2020-10-01T00:00:00-03:00 ... 2020 388938.0
2020-11-01 CAGED12_SALDON12 2020-11-01T00:00:00-03:00 ... 2020 408948.0
2020-12-01 CAGED12_SALDON12 2020-12-01T00:00:00-03:00 ... 2020 -82118.0
2021-01-01 CAGED12_SALDON12 2021-01-01T00:00:00-03:00 ... 2021 257059.0
2021-02-01 CAGED12_SALDON12 2021-02-01T00:00:00-03:00 ... 2021 397915.0
2021-03-01 CAGED12_SALDON12 2021-03-01T00:00:00-03:00 ... 2021 176330.0
2021-04-01 CAGED12_SALDON12 2021-04-01T00:00:00-03:00 ... 2021 113922.0
2021-05-01 CAGED12_SALDON12 2021-05-01T00:00:00-03:00 ... 2021 278705.0
2021-06-01 CAGED12_SALDON12 2021-06-01T00:00:00-03:00 ... 2021 310036.0
2021-07-01 CAGED12_SALDON12 2021-07-01T00:00:00-03:00 ... 2021 316725.0
2021-08-01 CAGED12_SALDON12 2021-08-01T00:00:00-03:00 ... 2021 373344.0
2021-09-01 CAGED12_SALDON12 2021-09-01T00:00:00-03:00 ... 2021 316993.0
2021-10-01 CAGED12_SALDON12 2021-10-01T00:00:00-03:00 ... 2021 253083.0
2021-11-01 CAGED12_SALDON12 2021-11-01T00:00:00-03:00 ... 2021 324112.0
2021-12-01 CAGED12_SALDON12 2021-12-01T00:00:00-03:00 ... 2021 -265811.0
2022-01-01 CAGED12_SALDON12 2022-01-01T00:00:00-03:00 ... 2022 155178.0
2022-02-01 CAGED12_SALDON12 2022-02-01T00:00:00-03:00 ... 2022 328507.0
2022-03-01 CAGED12_SALDON12 2022-03-01T00:00:00-03:00 ... 2022 136189.0
2022-04-01 CAGED12_SALDON12 2022-04-01T00:00:00-03:00 ... 2022 196966.0
2022-05-01 CAGED12_SALDON12 2022-05-01T00:00:00-03:00 ... 2022 277018.0
2022-06-01 CAGED12_SALDON12 2022-06-01T00:00:00-03:00 ... 2022 277944.0
2022-07-01 CAGED12_SALDON12 2022-07-01T00:00:00-03:00 ... 2022 218902.0
2022-08-01 CAGED12_SALDON12 2022-08-01T00:00:00-03:00 ... 2022 278639.0
2022-09-01 CAGED12_SALDON12 2022-09-01T00:00:00-03:00 ... 2022 278085.0
2022-10-01 CAGED12_SALDON12 2022-10-01T00:00:00-03:00 ... 2022 159454.0
2022-11-01 CAGED12_SALDON12 2022-11-01T00:00:00-03:00 ... 2022 135495.0
2022-12-01 CAGED12_SALDON12 2022-12-01T00:00:00-03:00 ... 2022 -431011.0
2023-01-01 CAGED12_SALDON12 2023-01-01T00:00:00-03:00 ... 2023 83297.0
2023-02-01 CAGED12_SALDON12 2023-02-01T00:00:00-03:00 ... 2023 241785.0
2023-03-01 CAGED12_SALDON12 2023-03-01T00:00:00-03:00 ... 2023 195171.0
2023-04-01 CAGED12_SALDON12 2023-04-01T00:00:00-03:00 ... 2023 180005.0
2023-05-01 CAGED12_SALDON12 2023-05-01T00:00:00-03:00 ... 2023 155270.0
2023-06-01 CAGED12_SALDON12 2023-06-01T00:00:00-03:00 ... 2023 157198.0
2023-07-01 CAGED12_SALDON12 2023-07-01T00:00:00-03:00 ... 2023 142702.0
2023-08-01 CAGED12_SALDON12 2023-08-01T00:00:00-03:00 ... 2023 220844.0
2023-09-01 CAGED12_SALDON12 2023-09-01T00:00:00-03:00 ... 2023 211764.0
2023-10-01 CAGED12_SALDON12 2023-10-01T00:00:00-03:00 ... 2023 190366.0
2023-11-01 CAGED12_SALDON12 2023-11-01T00:00:00-03:00 ... 2023 130097.0
2023-12-01 CAGED12_SALDON12 2023-12-01T00:00:00-03:00 ... 2023 -430159.0
2024-01-01 CAGED12_SALDON12 2024-01-01T00:00:00-03:00 ... 2024 180395.0
2024-02-01 CAGED12_SALDON12 2024-02-01T00:00:00-03:00 ... 2024 306111.0
2024-03-01 CAGED12_SALDON12 2024-03-01T00:00:00-03:00 ... 2024 244315.0
[51 rows x 6 columns]
tabela_idp = (
dados_sgs
.reset_index()
.rename(columns = {"Date": "data"})
.set_index("data")
)
tabela_idp idp
data
2019-11-01 74643.3
2019-12-01 69174.4
2020-01-01 69231.7
2020-02-01 65058.0
2020-03-01 69231.5
2020-04-01 65494.1
2020-05-01 59698.7
2020-06-01 63600.5
2020-07-01 62835.5
2020-08-01 53665.2
2020-09-01 50999.2
2020-10-01 46394.8
2020-11-01 39992.6
2020-12-01 38270.1
2021-01-01 38830.1
2021-02-01 45111.8
2021-03-01 46666.4
2021-04-01 50173.3
2021-05-01 48949.6
2021-06-01 43533.0
2021-07-01 46549.1
2021-08-01 50691.8
2021-09-01 50263.7
2021-10-01 50022.6
2021-11-01 52720.8
2021-12-01 46440.5
2022-01-01 47080.9
2022-02-01 47777.3
2022-03-01 45332.3
2022-04-01 51768.7
2022-05-01 53901.4
2022-06-01 57702.0
2022-07-01 57034.4
2022-08-01 60576.8
2022-09-01 67313.8
2022-10-01 68393.6
2022-11-01 69906.9
2022-12-01 74606.4
2023-01-01 77099.4
2023-02-01 74833.6
2023-03-01 75258.3
2023-04-01 67399.0
2023-05-01 68317.9
2023-06-01 66992.4
2023-07-01 66916.6
2023-08-01 64444.0
2023-09-01 60436.5
2023-10-01 60360.3
2023-11-01 62197.4
2023-12-01 64229.7
2024-01-01 66439.5
2024-02-01 64283.4
2024-03-01 66529.8
Para fazer o cruzamento usamos a função join() do pandas, usando a sintaxe tabela_x.join(other = tabela_y, how = "inner"). Por padrão o index das tabelas será usado como chave.
# Inner Join: cruzar tabelas mantendo todas as linhas "em comum" de x e y
tabela_caged.join(other = tabela_idp, how = "inner") CODE RAW DATE ... caged idp
data ...
2020-01-01 CAGED12_SALDON12 2020-01-01T00:00:00-03:00 ... 92678.0 69231.7
2020-02-01 CAGED12_SALDON12 2020-02-01T00:00:00-03:00 ... 198368.0 65058.0
2020-03-01 CAGED12_SALDON12 2020-03-01T00:00:00-03:00 ... -232316.0 69231.5
2020-04-01 CAGED12_SALDON12 2020-04-01T00:00:00-03:00 ... -902317.0 65494.1
2020-05-01 CAGED12_SALDON12 2020-05-01T00:00:00-03:00 ... -352790.0 59698.7
2020-06-01 CAGED12_SALDON12 2020-06-01T00:00:00-03:00 ... -23111.0 63600.5
2020-07-01 CAGED12_SALDON12 2020-07-01T00:00:00-03:00 ... 123297.0 62835.5
2020-08-01 CAGED12_SALDON12 2020-08-01T00:00:00-03:00 ... 238125.0 53665.2
2020-09-01 CAGED12_SALDON12 2020-09-01T00:00:00-03:00 ... 313564.0 50999.2
2020-10-01 CAGED12_SALDON12 2020-10-01T00:00:00-03:00 ... 388938.0 46394.8
2020-11-01 CAGED12_SALDON12 2020-11-01T00:00:00-03:00 ... 408948.0 39992.6
2020-12-01 CAGED12_SALDON12 2020-12-01T00:00:00-03:00 ... -82118.0 38270.1
2021-01-01 CAGED12_SALDON12 2021-01-01T00:00:00-03:00 ... 257059.0 38830.1
2021-02-01 CAGED12_SALDON12 2021-02-01T00:00:00-03:00 ... 397915.0 45111.8
2021-03-01 CAGED12_SALDON12 2021-03-01T00:00:00-03:00 ... 176330.0 46666.4
2021-04-01 CAGED12_SALDON12 2021-04-01T00:00:00-03:00 ... 113922.0 50173.3
2021-05-01 CAGED12_SALDON12 2021-05-01T00:00:00-03:00 ... 278705.0 48949.6
2021-06-01 CAGED12_SALDON12 2021-06-01T00:00:00-03:00 ... 310036.0 43533.0
2021-07-01 CAGED12_SALDON12 2021-07-01T00:00:00-03:00 ... 316725.0 46549.1
2021-08-01 CAGED12_SALDON12 2021-08-01T00:00:00-03:00 ... 373344.0 50691.8
2021-09-01 CAGED12_SALDON12 2021-09-01T00:00:00-03:00 ... 316993.0 50263.7
2021-10-01 CAGED12_SALDON12 2021-10-01T00:00:00-03:00 ... 253083.0 50022.6
2021-11-01 CAGED12_SALDON12 2021-11-01T00:00:00-03:00 ... 324112.0 52720.8
2021-12-01 CAGED12_SALDON12 2021-12-01T00:00:00-03:00 ... -265811.0 46440.5
2022-01-01 CAGED12_SALDON12 2022-01-01T00:00:00-03:00 ... 155178.0 47080.9
2022-02-01 CAGED12_SALDON12 2022-02-01T00:00:00-03:00 ... 328507.0 47777.3
2022-03-01 CAGED12_SALDON12 2022-03-01T00:00:00-03:00 ... 136189.0 45332.3
2022-04-01 CAGED12_SALDON12 2022-04-01T00:00:00-03:00 ... 196966.0 51768.7
2022-05-01 CAGED12_SALDON12 2022-05-01T00:00:00-03:00 ... 277018.0 53901.4
2022-06-01 CAGED12_SALDON12 2022-06-01T00:00:00-03:00 ... 277944.0 57702.0
2022-07-01 CAGED12_SALDON12 2022-07-01T00:00:00-03:00 ... 218902.0 57034.4
2022-08-01 CAGED12_SALDON12 2022-08-01T00:00:00-03:00 ... 278639.0 60576.8
2022-09-01 CAGED12_SALDON12 2022-09-01T00:00:00-03:00 ... 278085.0 67313.8
2022-10-01 CAGED12_SALDON12 2022-10-01T00:00:00-03:00 ... 159454.0 68393.6
2022-11-01 CAGED12_SALDON12 2022-11-01T00:00:00-03:00 ... 135495.0 69906.9
2022-12-01 CAGED12_SALDON12 2022-12-01T00:00:00-03:00 ... -431011.0 74606.4
2023-01-01 CAGED12_SALDON12 2023-01-01T00:00:00-03:00 ... 83297.0 77099.4
2023-02-01 CAGED12_SALDON12 2023-02-01T00:00:00-03:00 ... 241785.0 74833.6
2023-03-01 CAGED12_SALDON12 2023-03-01T00:00:00-03:00 ... 195171.0 75258.3
2023-04-01 CAGED12_SALDON12 2023-04-01T00:00:00-03:00 ... 180005.0 67399.0
2023-05-01 CAGED12_SALDON12 2023-05-01T00:00:00-03:00 ... 155270.0 68317.9
2023-06-01 CAGED12_SALDON12 2023-06-01T00:00:00-03:00 ... 157198.0 66992.4
2023-07-01 CAGED12_SALDON12 2023-07-01T00:00:00-03:00 ... 142702.0 66916.6
2023-08-01 CAGED12_SALDON12 2023-08-01T00:00:00-03:00 ... 220844.0 64444.0
2023-09-01 CAGED12_SALDON12 2023-09-01T00:00:00-03:00 ... 211764.0 60436.5
2023-10-01 CAGED12_SALDON12 2023-10-01T00:00:00-03:00 ... 190366.0 60360.3
2023-11-01 CAGED12_SALDON12 2023-11-01T00:00:00-03:00 ... 130097.0 62197.4
2023-12-01 CAGED12_SALDON12 2023-12-01T00:00:00-03:00 ... -430159.0 64229.7
2024-01-01 CAGED12_SALDON12 2024-01-01T00:00:00-03:00 ... 180395.0 66439.5
2024-02-01 CAGED12_SALDON12 2024-02-01T00:00:00-03:00 ... 306111.0 64283.4
2024-03-01 CAGED12_SALDON12 2024-03-01T00:00:00-03:00 ... 244315.0 66529.8
[51 rows x 7 columns]
No cruzamento do tipo inner join é bastante fácil perder observações que poderiam ser importantes para sua análise, pois as linhas sem correspondência não são incluídas no resultado final.
Cruzamentos outer join
O mais utilizado é o left join.
# Left Join: cruzar tabelas mantendo todas as linhas de x
tabela_caged.join(other = tabela_idp, how = "left") CODE RAW DATE ... caged idp
data ...
2020-01-01 CAGED12_SALDON12 2020-01-01T00:00:00-03:00 ... 92678.0 69231.7
2020-02-01 CAGED12_SALDON12 2020-02-01T00:00:00-03:00 ... 198368.0 65058.0
2020-03-01 CAGED12_SALDON12 2020-03-01T00:00:00-03:00 ... -232316.0 69231.5
2020-04-01 CAGED12_SALDON12 2020-04-01T00:00:00-03:00 ... -902317.0 65494.1
2020-05-01 CAGED12_SALDON12 2020-05-01T00:00:00-03:00 ... -352790.0 59698.7
2020-06-01 CAGED12_SALDON12 2020-06-01T00:00:00-03:00 ... -23111.0 63600.5
2020-07-01 CAGED12_SALDON12 2020-07-01T00:00:00-03:00 ... 123297.0 62835.5
2020-08-01 CAGED12_SALDON12 2020-08-01T00:00:00-03:00 ... 238125.0 53665.2
2020-09-01 CAGED12_SALDON12 2020-09-01T00:00:00-03:00 ... 313564.0 50999.2
2020-10-01 CAGED12_SALDON12 2020-10-01T00:00:00-03:00 ... 388938.0 46394.8
2020-11-01 CAGED12_SALDON12 2020-11-01T00:00:00-03:00 ... 408948.0 39992.6
2020-12-01 CAGED12_SALDON12 2020-12-01T00:00:00-03:00 ... -82118.0 38270.1
2021-01-01 CAGED12_SALDON12 2021-01-01T00:00:00-03:00 ... 257059.0 38830.1
2021-02-01 CAGED12_SALDON12 2021-02-01T00:00:00-03:00 ... 397915.0 45111.8
2021-03-01 CAGED12_SALDON12 2021-03-01T00:00:00-03:00 ... 176330.0 46666.4
2021-04-01 CAGED12_SALDON12 2021-04-01T00:00:00-03:00 ... 113922.0 50173.3
2021-05-01 CAGED12_SALDON12 2021-05-01T00:00:00-03:00 ... 278705.0 48949.6
2021-06-01 CAGED12_SALDON12 2021-06-01T00:00:00-03:00 ... 310036.0 43533.0
2021-07-01 CAGED12_SALDON12 2021-07-01T00:00:00-03:00 ... 316725.0 46549.1
2021-08-01 CAGED12_SALDON12 2021-08-01T00:00:00-03:00 ... 373344.0 50691.8
2021-09-01 CAGED12_SALDON12 2021-09-01T00:00:00-03:00 ... 316993.0 50263.7
2021-10-01 CAGED12_SALDON12 2021-10-01T00:00:00-03:00 ... 253083.0 50022.6
2021-11-01 CAGED12_SALDON12 2021-11-01T00:00:00-03:00 ... 324112.0 52720.8
2021-12-01 CAGED12_SALDON12 2021-12-01T00:00:00-03:00 ... -265811.0 46440.5
2022-01-01 CAGED12_SALDON12 2022-01-01T00:00:00-03:00 ... 155178.0 47080.9
2022-02-01 CAGED12_SALDON12 2022-02-01T00:00:00-03:00 ... 328507.0 47777.3
2022-03-01 CAGED12_SALDON12 2022-03-01T00:00:00-03:00 ... 136189.0 45332.3
2022-04-01 CAGED12_SALDON12 2022-04-01T00:00:00-03:00 ... 196966.0 51768.7
2022-05-01 CAGED12_SALDON12 2022-05-01T00:00:00-03:00 ... 277018.0 53901.4
2022-06-01 CAGED12_SALDON12 2022-06-01T00:00:00-03:00 ... 277944.0 57702.0
2022-07-01 CAGED12_SALDON12 2022-07-01T00:00:00-03:00 ... 218902.0 57034.4
2022-08-01 CAGED12_SALDON12 2022-08-01T00:00:00-03:00 ... 278639.0 60576.8
2022-09-01 CAGED12_SALDON12 2022-09-01T00:00:00-03:00 ... 278085.0 67313.8
2022-10-01 CAGED12_SALDON12 2022-10-01T00:00:00-03:00 ... 159454.0 68393.6
2022-11-01 CAGED12_SALDON12 2022-11-01T00:00:00-03:00 ... 135495.0 69906.9
2022-12-01 CAGED12_SALDON12 2022-12-01T00:00:00-03:00 ... -431011.0 74606.4
2023-01-01 CAGED12_SALDON12 2023-01-01T00:00:00-03:00 ... 83297.0 77099.4
2023-02-01 CAGED12_SALDON12 2023-02-01T00:00:00-03:00 ... 241785.0 74833.6
2023-03-01 CAGED12_SALDON12 2023-03-01T00:00:00-03:00 ... 195171.0 75258.3
2023-04-01 CAGED12_SALDON12 2023-04-01T00:00:00-03:00 ... 180005.0 67399.0
2023-05-01 CAGED12_SALDON12 2023-05-01T00:00:00-03:00 ... 155270.0 68317.9
2023-06-01 CAGED12_SALDON12 2023-06-01T00:00:00-03:00 ... 157198.0 66992.4
2023-07-01 CAGED12_SALDON12 2023-07-01T00:00:00-03:00 ... 142702.0 66916.6
2023-08-01 CAGED12_SALDON12 2023-08-01T00:00:00-03:00 ... 220844.0 64444.0
2023-09-01 CAGED12_SALDON12 2023-09-01T00:00:00-03:00 ... 211764.0 60436.5
2023-10-01 CAGED12_SALDON12 2023-10-01T00:00:00-03:00 ... 190366.0 60360.3
2023-11-01 CAGED12_SALDON12 2023-11-01T00:00:00-03:00 ... 130097.0 62197.4
2023-12-01 CAGED12_SALDON12 2023-12-01T00:00:00-03:00 ... -430159.0 64229.7
2024-01-01 CAGED12_SALDON12 2024-01-01T00:00:00-03:00 ... 180395.0 66439.5
2024-02-01 CAGED12_SALDON12 2024-02-01T00:00:00-03:00 ... 306111.0 64283.4
2024-03-01 CAGED12_SALDON12 2024-03-01T00:00:00-03:00 ... 244315.0 66529.8
[51 rows x 7 columns]
Por sua vez, o right join:
# Right Join: cruzar tabelas mantendo todas as linhas de y
tabela_caged.join(other = tabela_idp, how = "right") CODE RAW DATE ... caged idp
data ...
2019-11-01 NaN NaN ... NaN 74643.3
2019-12-01 NaN NaN ... NaN 69174.4
2020-01-01 CAGED12_SALDON12 2020-01-01T00:00:00-03:00 ... 92678.0 69231.7
2020-02-01 CAGED12_SALDON12 2020-02-01T00:00:00-03:00 ... 198368.0 65058.0
2020-03-01 CAGED12_SALDON12 2020-03-01T00:00:00-03:00 ... -232316.0 69231.5
2020-04-01 CAGED12_SALDON12 2020-04-01T00:00:00-03:00 ... -902317.0 65494.1
2020-05-01 CAGED12_SALDON12 2020-05-01T00:00:00-03:00 ... -352790.0 59698.7
2020-06-01 CAGED12_SALDON12 2020-06-01T00:00:00-03:00 ... -23111.0 63600.5
2020-07-01 CAGED12_SALDON12 2020-07-01T00:00:00-03:00 ... 123297.0 62835.5
2020-08-01 CAGED12_SALDON12 2020-08-01T00:00:00-03:00 ... 238125.0 53665.2
2020-09-01 CAGED12_SALDON12 2020-09-01T00:00:00-03:00 ... 313564.0 50999.2
2020-10-01 CAGED12_SALDON12 2020-10-01T00:00:00-03:00 ... 388938.0 46394.8
2020-11-01 CAGED12_SALDON12 2020-11-01T00:00:00-03:00 ... 408948.0 39992.6
2020-12-01 CAGED12_SALDON12 2020-12-01T00:00:00-03:00 ... -82118.0 38270.1
2021-01-01 CAGED12_SALDON12 2021-01-01T00:00:00-03:00 ... 257059.0 38830.1
2021-02-01 CAGED12_SALDON12 2021-02-01T00:00:00-03:00 ... 397915.0 45111.8
2021-03-01 CAGED12_SALDON12 2021-03-01T00:00:00-03:00 ... 176330.0 46666.4
2021-04-01 CAGED12_SALDON12 2021-04-01T00:00:00-03:00 ... 113922.0 50173.3
2021-05-01 CAGED12_SALDON12 2021-05-01T00:00:00-03:00 ... 278705.0 48949.6
2021-06-01 CAGED12_SALDON12 2021-06-01T00:00:00-03:00 ... 310036.0 43533.0
2021-07-01 CAGED12_SALDON12 2021-07-01T00:00:00-03:00 ... 316725.0 46549.1
2021-08-01 CAGED12_SALDON12 2021-08-01T00:00:00-03:00 ... 373344.0 50691.8
2021-09-01 CAGED12_SALDON12 2021-09-01T00:00:00-03:00 ... 316993.0 50263.7
2021-10-01 CAGED12_SALDON12 2021-10-01T00:00:00-03:00 ... 253083.0 50022.6
2021-11-01 CAGED12_SALDON12 2021-11-01T00:00:00-03:00 ... 324112.0 52720.8
2021-12-01 CAGED12_SALDON12 2021-12-01T00:00:00-03:00 ... -265811.0 46440.5
2022-01-01 CAGED12_SALDON12 2022-01-01T00:00:00-03:00 ... 155178.0 47080.9
2022-02-01 CAGED12_SALDON12 2022-02-01T00:00:00-03:00 ... 328507.0 47777.3
2022-03-01 CAGED12_SALDON12 2022-03-01T00:00:00-03:00 ... 136189.0 45332.3
2022-04-01 CAGED12_SALDON12 2022-04-01T00:00:00-03:00 ... 196966.0 51768.7
2022-05-01 CAGED12_SALDON12 2022-05-01T00:00:00-03:00 ... 277018.0 53901.4
2022-06-01 CAGED12_SALDON12 2022-06-01T00:00:00-03:00 ... 277944.0 57702.0
2022-07-01 CAGED12_SALDON12 2022-07-01T00:00:00-03:00 ... 218902.0 57034.4
2022-08-01 CAGED12_SALDON12 2022-08-01T00:00:00-03:00 ... 278639.0 60576.8
2022-09-01 CAGED12_SALDON12 2022-09-01T00:00:00-03:00 ... 278085.0 67313.8
2022-10-01 CAGED12_SALDON12 2022-10-01T00:00:00-03:00 ... 159454.0 68393.6
2022-11-01 CAGED12_SALDON12 2022-11-01T00:00:00-03:00 ... 135495.0 69906.9
2022-12-01 CAGED12_SALDON12 2022-12-01T00:00:00-03:00 ... -431011.0 74606.4
2023-01-01 CAGED12_SALDON12 2023-01-01T00:00:00-03:00 ... 83297.0 77099.4
2023-02-01 CAGED12_SALDON12 2023-02-01T00:00:00-03:00 ... 241785.0 74833.6
2023-03-01 CAGED12_SALDON12 2023-03-01T00:00:00-03:00 ... 195171.0 75258.3
2023-04-01 CAGED12_SALDON12 2023-04-01T00:00:00-03:00 ... 180005.0 67399.0
2023-05-01 CAGED12_SALDON12 2023-05-01T00:00:00-03:00 ... 155270.0 68317.9
2023-06-01 CAGED12_SALDON12 2023-06-01T00:00:00-03:00 ... 157198.0 66992.4
2023-07-01 CAGED12_SALDON12 2023-07-01T00:00:00-03:00 ... 142702.0 66916.6
2023-08-01 CAGED12_SALDON12 2023-08-01T00:00:00-03:00 ... 220844.0 64444.0
2023-09-01 CAGED12_SALDON12 2023-09-01T00:00:00-03:00 ... 211764.0 60436.5
2023-10-01 CAGED12_SALDON12 2023-10-01T00:00:00-03:00 ... 190366.0 60360.3
2023-11-01 CAGED12_SALDON12 2023-11-01T00:00:00-03:00 ... 130097.0 62197.4
2023-12-01 CAGED12_SALDON12 2023-12-01T00:00:00-03:00 ... -430159.0 64229.7
2024-01-01 CAGED12_SALDON12 2024-01-01T00:00:00-03:00 ... 180395.0 66439.5
2024-02-01 CAGED12_SALDON12 2024-02-01T00:00:00-03:00 ... 306111.0 64283.4
2024-03-01 CAGED12_SALDON12 2024-03-01T00:00:00-03:00 ... 244315.0 66529.8
[53 rows x 7 columns]
E por último, o full join:
# Full Join: cruzar tabelas mantendo todas as linhas de x ou y
tabela_caged.join(other = tabela_idp, how = "outer") CODE RAW DATE ... caged idp
data ...
2019-11-01 NaN NaN ... NaN 74643.3
2019-12-01 NaN NaN ... NaN 69174.4
2020-01-01 CAGED12_SALDON12 2020-01-01T00:00:00-03:00 ... 92678.0 69231.7
2020-02-01 CAGED12_SALDON12 2020-02-01T00:00:00-03:00 ... 198368.0 65058.0
2020-03-01 CAGED12_SALDON12 2020-03-01T00:00:00-03:00 ... -232316.0 69231.5
2020-04-01 CAGED12_SALDON12 2020-04-01T00:00:00-03:00 ... -902317.0 65494.1
2020-05-01 CAGED12_SALDON12 2020-05-01T00:00:00-03:00 ... -352790.0 59698.7
2020-06-01 CAGED12_SALDON12 2020-06-01T00:00:00-03:00 ... -23111.0 63600.5
2020-07-01 CAGED12_SALDON12 2020-07-01T00:00:00-03:00 ... 123297.0 62835.5
2020-08-01 CAGED12_SALDON12 2020-08-01T00:00:00-03:00 ... 238125.0 53665.2
2020-09-01 CAGED12_SALDON12 2020-09-01T00:00:00-03:00 ... 313564.0 50999.2
2020-10-01 CAGED12_SALDON12 2020-10-01T00:00:00-03:00 ... 388938.0 46394.8
2020-11-01 CAGED12_SALDON12 2020-11-01T00:00:00-03:00 ... 408948.0 39992.6
2020-12-01 CAGED12_SALDON12 2020-12-01T00:00:00-03:00 ... -82118.0 38270.1
2021-01-01 CAGED12_SALDON12 2021-01-01T00:00:00-03:00 ... 257059.0 38830.1
2021-02-01 CAGED12_SALDON12 2021-02-01T00:00:00-03:00 ... 397915.0 45111.8
2021-03-01 CAGED12_SALDON12 2021-03-01T00:00:00-03:00 ... 176330.0 46666.4
2021-04-01 CAGED12_SALDON12 2021-04-01T00:00:00-03:00 ... 113922.0 50173.3
2021-05-01 CAGED12_SALDON12 2021-05-01T00:00:00-03:00 ... 278705.0 48949.6
2021-06-01 CAGED12_SALDON12 2021-06-01T00:00:00-03:00 ... 310036.0 43533.0
2021-07-01 CAGED12_SALDON12 2021-07-01T00:00:00-03:00 ... 316725.0 46549.1
2021-08-01 CAGED12_SALDON12 2021-08-01T00:00:00-03:00 ... 373344.0 50691.8
2021-09-01 CAGED12_SALDON12 2021-09-01T00:00:00-03:00 ... 316993.0 50263.7
2021-10-01 CAGED12_SALDON12 2021-10-01T00:00:00-03:00 ... 253083.0 50022.6
2021-11-01 CAGED12_SALDON12 2021-11-01T00:00:00-03:00 ... 324112.0 52720.8
2021-12-01 CAGED12_SALDON12 2021-12-01T00:00:00-03:00 ... -265811.0 46440.5
2022-01-01 CAGED12_SALDON12 2022-01-01T00:00:00-03:00 ... 155178.0 47080.9
2022-02-01 CAGED12_SALDON12 2022-02-01T00:00:00-03:00 ... 328507.0 47777.3
2022-03-01 CAGED12_SALDON12 2022-03-01T00:00:00-03:00 ... 136189.0 45332.3
2022-04-01 CAGED12_SALDON12 2022-04-01T00:00:00-03:00 ... 196966.0 51768.7
2022-05-01 CAGED12_SALDON12 2022-05-01T00:00:00-03:00 ... 277018.0 53901.4
2022-06-01 CAGED12_SALDON12 2022-06-01T00:00:00-03:00 ... 277944.0 57702.0
2022-07-01 CAGED12_SALDON12 2022-07-01T00:00:00-03:00 ... 218902.0 57034.4
2022-08-01 CAGED12_SALDON12 2022-08-01T00:00:00-03:00 ... 278639.0 60576.8
2022-09-01 CAGED12_SALDON12 2022-09-01T00:00:00-03:00 ... 278085.0 67313.8
2022-10-01 CAGED12_SALDON12 2022-10-01T00:00:00-03:00 ... 159454.0 68393.6
2022-11-01 CAGED12_SALDON12 2022-11-01T00:00:00-03:00 ... 135495.0 69906.9
2022-12-01 CAGED12_SALDON12 2022-12-01T00:00:00-03:00 ... -431011.0 74606.4
2023-01-01 CAGED12_SALDON12 2023-01-01T00:00:00-03:00 ... 83297.0 77099.4
2023-02-01 CAGED12_SALDON12 2023-02-01T00:00:00-03:00 ... 241785.0 74833.6
2023-03-01 CAGED12_SALDON12 2023-03-01T00:00:00-03:00 ... 195171.0 75258.3
2023-04-01 CAGED12_SALDON12 2023-04-01T00:00:00-03:00 ... 180005.0 67399.0
2023-05-01 CAGED12_SALDON12 2023-05-01T00:00:00-03:00 ... 155270.0 68317.9
2023-06-01 CAGED12_SALDON12 2023-06-01T00:00:00-03:00 ... 157198.0 66992.4
2023-07-01 CAGED12_SALDON12 2023-07-01T00:00:00-03:00 ... 142702.0 66916.6
2023-08-01 CAGED12_SALDON12 2023-08-01T00:00:00-03:00 ... 220844.0 64444.0
2023-09-01 CAGED12_SALDON12 2023-09-01T00:00:00-03:00 ... 211764.0 60436.5
2023-10-01 CAGED12_SALDON12 2023-10-01T00:00:00-03:00 ... 190366.0 60360.3
2023-11-01 CAGED12_SALDON12 2023-11-01T00:00:00-03:00 ... 130097.0 62197.4
2023-12-01 CAGED12_SALDON12 2023-12-01T00:00:00-03:00 ... -430159.0 64229.7
2024-01-01 CAGED12_SALDON12 2024-01-01T00:00:00-03:00 ... 180395.0 66439.5
2024-02-01 CAGED12_SALDON12 2024-02-01T00:00:00-03:00 ... 306111.0 64283.4
2024-03-01 CAGED12_SALDON12 2024-03-01T00:00:00-03:00 ... 244315.0 66529.8
[53 rows x 7 columns]
Trabalhando com Datas no Python
No Python, pode-se definir os tipos de dados para datas para os seguintes tipos:
- data: armazena uma data de calendário
- time: armazena a hora do dia na forma de horas, minutos, segundos e microssegundos
- datetime: armazena data e hora
- timedelta: diferença entre dois valores de datas
- tzinfo: fuso horário (time zone)
Para especificação de formatos de datas, é comum usar o padrão %Y para ano com quatro dígitos, %m para mês com dois dígitos e %d para dia com dois dígitos, formando o padrão %Y-%m-%d, comum para a importação de diversos dados em séries temporais ao redor do mundo. Ainda é possível que seja adicionado %H, que representa as horas em formato de 24h.
Existem diversos outros formatos para anos, meses, dias e horas, seguindo a lista abaixo:
ano
- %y: ano de dois dígitos (22)
- %Y: ano de quatro dígitos (2022)
mês
- %b: Mês abreviado (Mar)
- %B: Nomes completos de meses (March)
- %m: Mês como número (03 ou 3)
dia
- %d: Dia do mês (30)
dia da semana
- %a: Nome abreviado (Wed)
- %A: Nome completo
- %w: número (3 - Sunday sempre como 0 até Saturday como 6)
horas
- %H: 24 horas (00 até 23)
- %I: 12 horas (01 até 12)
- %M: minutos (01 até 59)
segundos
- %S: segundos de 00 até 59
AM/PM
- %p: utilizado junto com horas em formatos de 12 horas
Existem diversas formas de representar datas no Python, a mais comum é o formato internacional “YYYY-MM-DD”, padrão na biblioteca pandas.
# Importar bibliotecas
import pandas as pd
import datetime
import numpy as np
hoje = pd.to_datetime("2024-05-27")
hojeTimestamp('2024-05-27 00:00:00')
O tipo de um objeto escalar neste formato é Timestamp e em uma pandas Series é datetime64[ns]:
type(hoje)<class 'pandas._libs.tslibs.timestamps.Timestamp'>
pd.Series(hoje).info()<class 'pandas.core.series.Series'>
RangeIndex: 1 entries, 0 to 0
Series name: None
Non-Null Count Dtype
-------------- -----
1 non-null datetime64[ns]
dtypes: datetime64[ns](1)
memory usage: 140.0 bytes
Criando datas com diferentes formatos
A função to_datetime() possibilita criar datas e interpreta formatos variados e não padronizados. Por exemplo:
# Cria um objeto datetime do pandas a partir de datas de variados formatos
pd.to_datetime(["2024-05-27", "2024/05/28", "20240529", np.datetime64("2024-05-26"), datetime.datetime(2024, 5, 27)], format='mixed')DatetimeIndex(['2024-05-27', '2024-05-28', '2024-05-29', '2024-05-26',
'2024-05-27'],
dtype='datetime64[ns]', freq=None)
Se precisar, e em caso de erros, é importante especificar o formato atual da data (link) para que a função consiga convertê-la para o padrão internacional:
pd.to_datetime("28/02/2023", format = "%d/%m/%Y")Timestamp('2023-02-28 00:00:00')
Alterando a representação da data
Podemos mudar a representação da data para um formato diferente, conforme a necessidade, usando to_period() e to_timestamp(). Por exemplo:
# Converte data para outras frequências
hoje.to_period(freq = "M") # mensalPeriod('2024-05', 'M')
hoje.to_period(freq = "Q") # trimestralPeriod('2024Q2', 'Q-DEC')
hoje.to_period(freq = "Y") # anualPeriod('2024', 'Y-DEC')
# Retorna data para formato internacional
hoje.to_period(freq = "M").to_timestamp(freq = "D") # converte para YYYY-MM-DD Timestamp('2024-05-01 00:00:00')
hoje.to_period(freq = "Q").to_timestamp(freq = "D", how = "End") # converte para YYYY-MM-DD com dia no final do períodoTimestamp('2024-06-30 23:59:59.999999999')
Criando sequências de datas
Com a função date_range() é possível criar sequências de datas com frequência fixa (neste link a lista de códigos de frequências úteis). Por exemplo:
# Sequência de datas de frequência mensal de início a fim
pd.date_range(start = "2023-01-01", end = "2023-12-01", freq = "MS")DatetimeIndex(['2023-01-01', '2023-02-01', '2023-03-01', '2023-04-01',
'2023-05-01', '2023-06-01', '2023-07-01', '2023-08-01',
'2023-09-01', '2023-10-01', '2023-11-01', '2023-12-01'],
dtype='datetime64[ns]', freq='MS')
# Sequência de datas de frequência mensal de início + nº de períodos
pd.date_range(start = "2023-01-01", periods = 12, freq = "MS")DatetimeIndex(['2023-01-01', '2023-02-01', '2023-03-01', '2023-04-01',
'2023-05-01', '2023-06-01', '2023-07-01', '2023-08-01',
'2023-09-01', '2023-10-01', '2023-11-01', '2023-12-01'],
dtype='datetime64[ns]', freq='MS')
Componentes de datas
Existem diversos componentes úteis que podem ser acessados de um Timestamp ou uma coleção de Timestamp, como um DatetimeIndex:
# Cria sequência de datas
datas = pd.date_range(start = "2023-01-01", periods = 2, freq = "MS")Extrai componentes das datas:
datas.year # anoIndex([2023, 2023], dtype='int32')
datas.month # mêsIndex([1, 2], dtype='int32')
datas.day # diaIndex([1, 1], dtype='int32')
Em caso de ter uma pandas Series com datas, use o acessor .dt para acessar estes componentes:
pd.Series(datas).dt.month0 1
1 2
dtype: int32
Identificando e Tratando Dados Faltantes
# Importar bibliotecas
import pandas as pd
import numpy as np
import ipeadatapy as ipea
from bcb import sgs
# Dados do saldo do CAGED (Ipeadata)
dados_ipeadata = (
ipea.timeseries("CAGED12_SALDON12")
.rename_axis("data", axis = "index")
.rename(columns = {"VALUE (Pessoa)": "caged"})
.filter(items = ["caged"], axis = "columns")
.query("data <= '2020-06-01'")
)
# Dados do IDP/BP - acum. 12m - US$ (milhões) (SGS/BCB)
dados_sgs = (
sgs.get(
codes = {"idp": 24422},
start = "2019-11-01",
end = "2020-03-01")
.rename_axis("data", axis = "index")
)
# Cruzamento de dados
tabela = dados_ipeadata.join(other = dados_sgs, how = "outer")tabela caged idp
data
2019-11-01 NaN 74643.3
2019-12-01 NaN 69174.4
2020-01-01 92678.0 69231.7
2020-02-01 198368.0 65058.0
2020-03-01 -232316.0 69231.5
2020-04-01 -902317.0 NaN
2020-05-01 -352790.0 NaN
2020-06-01 -23111.0 NaN
Como identificar se há NaN em uma tabela? Por código, basta usar isna() sobre uma coluna ou DataFrame, o retorno é True ou False, ou fazer um filtro para trazer somentes os casos verdadeiros:
# Testa quais observações são NaN
tabela.isna() caged idp
data
2019-11-01 True False
2019-12-01 True False
2020-01-01 False False
2020-02-01 False False
2020-03-01 False False
2020-04-01 False True
2020-05-01 False True
2020-06-01 False True
# Filtrando linhas com NaN (uma única coluna)
tabela.query("caged.isna()") caged idp
data
2019-11-01 NaN 74643.3
2019-12-01 NaN 69174.4
A mesma lógica pode ser seguida para mais de uma coluna. Neste caso, o operador or pode ser útil no filtro, pois retorna valores lógicos True para quaisquer das linhas das colunas especificadas quem possuam NaN:
# Filtrando linhas com NaN (+ de 1 coluna)
tabela.query("caged.isna() or idp.isna()") caged idp
data
2019-11-01 NaN 74643.3
2019-12-01 NaN 69174.4
2020-04-01 -902317.0 NaN
2020-05-01 -352790.0 NaN
2020-06-01 -23111.0 NaN
Caso não senqueira apenas identificar quais linhas de quais colunas possuem NaN, mas sim contabilizar os NaN por cada variável, deve-se usar um for-loop: a ideia é somar o número de NaN por coluna, a função lambda np.sum(x.isna()) faz isso. Optou-se por usar a função apply() para o loop, mas é possível usar abordagens diferentes e obter os mesmos resultados:
# Quantos NaN existem por coluna? Use um for-loop:
tabela.apply(lambda x: np.sum(x.isna()))caged 2
idp 3
dtype: int64
O mesmo resultado poderia ter sido obtido usando outras ferramentas do pandas:
tabela.agg(func = lambda x: np.sum(x.isna()), axis = "index")caged 2
idp 3
dtype: int64
Tratando NaN: remoção
Se foram identificada as linhas com NaN em uma coluna e o objetivo é removê-las, deve-se usar a função dropna():
# Removendo linhas com NaN (de uma única coluna)
tabela.dropna(subset = ["caged"]) caged idp
data
2020-01-01 92678.0 69231.7
2020-02-01 198368.0 65058.0
2020-03-01 -232316.0 69231.5
2020-04-01 -902317.0 NaN
2020-05-01 -352790.0 NaN
2020-06-01 -23111.0 NaN
# Removendo linhas com NaN (de todas as colunas)
tabela.dropna() caged idp
data
2020-01-01 92678.0 69231.7
2020-02-01 198368.0 65058.0
2020-03-01 -232316.0 69231.5
Tratando NaN: substituição
Se remover as linhas com NaN não for viável, deve-se substituir as obsevações ausentes por outros valores. Os valores que entrarão no lugar dos NaN são definidos por critério do usuário, mas é comum usar a média da variável ou o valor da observação anterior (para séries temporais). Isso pode ser feito com a função fillna() do pandas:
( # Substituindo valores NaN
tabela
# substituir NaN pela média histórica
.fillna(value = {"caged": tabela.caged.mean()})
# substituir NaN pelo último valor observado
.fillna(method = "ffill")
) caged idp
data
2019-11-01 -203248.0 74643.3
2019-12-01 -203248.0 69174.4
2020-01-01 92678.0 69231.7
2020-02-01 198368.0 65058.0
2020-03-01 -232316.0 69231.5
2020-04-01 -902317.0 69231.5
2020-05-01 -352790.0 69231.5
2020-06-01 -23111.0 69231.5
Outra possibilidade é o uso da função combine_first() do pandas que possibilita substituir NaN de uma coluna com base em valores ao lado (de outra coluna):
# Substituindo valores NaN de uma coluna por valores de outra coluna
tabela.assign(
# substitui NaN de idp por valores em caged
idp = tabela.idp.combine_first(tabela.caged)
) caged idp
data
2019-11-01 NaN 74643.3
2019-12-01 NaN 69174.4
2020-01-01 92678.0 69231.7
2020-02-01 198368.0 65058.0
2020-03-01 -232316.0 69231.5
2020-04-01 -902317.0 -902317.0
2020-05-01 -352790.0 -352790.0
2020-06-01 -23111.0 -23111.0
Note que a substituição acima não faz sentido em uma análise de dados, pois são variáveis distintas, constituindo apenas um exemplo didático.
Como Deflacionar uma série
# Importar bibliotecas
import pandas as pd
import ipeadatapy as ipea
# Dados de valores nominais: salário mínimo vigente (R$, Ipeadata)
dados_nominais = (
ipea.timeseries("MTE12_SALMIN12")
.rename_axis("data", axis = "index")
.rename(columns = {"VALUE (R$)": "nominal"})
.filter(items = ["nominal"], axis = "columns")
.query("data >= '2000-01-01'")
)
# Dados de índice de preços: INPC (índice 12/1993 = 100, Sidra/IBGE)
dados_indice = (
pd.read_json(
path_or_buf = "https://apisidra.ibge.gov.br/values/t/1736/n1/all/v/2289/p/all/d/v2289%2013?formato=json"
)
.rename(columns = {"V": "indice", "D3C": "data"})
.query("indice != 'Valor'")
.filter(items = ["data", "indice"])
.assign(
data = lambda x: pd.to_datetime(x.data, format = "%Y%m"),
indice = lambda x: x.indice.astype(float)
)
.set_index("data")
)dados_nominais nominal
data
2000-01-01 136.0
2000-02-01 136.0
2000-03-01 136.0
2000-04-01 151.0
2000-05-01 151.0
... ...
2024-08-01 1412.0
2024-09-01 1412.0
2024-10-01 1412.0
2024-11-01 1412.0
2024-12-01 1412.0
[300 rows x 1 columns]
dados_indice indice
data
1979-03-01 5.576500e-09
1979-04-01 5.768900e-09
1979-05-01 5.870400e-09
1979-06-01 6.046500e-09
1979-07-01 6.370500e-09
... ...
2023-12-01 6.954740e+03
2024-01-01 6.994380e+03
2024-02-01 7.051030e+03
2024-03-01 7.064430e+03
2024-04-01 7.090570e+03
[542 rows x 1 columns]
Após ter os dados necessários já tratados, basta cruzar as tabelas e aplicar a fórmula de deflacionamento, que envolve calcular um fator de deflacionamento usando uma data base (neste exemplo é o último mês observado) e multiplicar este fator pela série nominal:
\[Vr_{i:j} = (\frac{I_{j}}{I_{i}}) * V_{i}\] onde:
\(Vr_{i:j}\) é o valor real, ou deflacionado, no período \(i\) na data-base \(j\)
\(I_{j}\) é o índice de preços fixado na data-base \(j\)
\(I_{i}\) é o índice de preços no período \(i\)
\(V_{i}\) é o valor ou preço nominal no período \(i\)
# Cruzar tabelas
tabela = dados_nominais.join(other = dados_indice, how = "inner")
# Deflacionar a série com data base = último mês observado
indice_data_base = tabela.query("data == data.max()").indice.values
tabela.assign(real = lambda x: (indice_data_base / x.indice) * x.nominal).tail() nominal indice real
data
2023-12-01 1320.0 6954.74 1345.780345
2024-01-01 1412.0 6994.38 1431.418487
2024-02-01 1412.0 7051.03 1419.918060
2024-03-01 1412.0 7064.43 1417.224722
2024-04-01 1412.0 7090.57 1412.000000
Como fazer um ajuste sazonal?
# Importar bibliotecas
#pip install python-dateutil
from statsmodels.tsa.seasonal import seasonal_decompose
from dateutil.parser import parse
import pandas as pd
dados = (
pd.read_csv("dados/empregados.csv")
.assign(data = lambda x: pd.to_datetime(x.data))
.set_index("data")
)
dados empregados_no_varejo
data
1995-01-01 13775.2
1995-02-01 13579.5
1995-03-01 13539.2
1995-04-01 13654.1
1995-05-01 13757.5
... ...
2019-05-01 15691.6
2019-06-01 15775.5
2019-07-01 15785.9
2019-08-01 15749.5
2019-09-01 15611.3
[297 rows x 1 columns]
# Performa o ajuste sazonal
ajuste = seasonal_decompose(dados['empregados_no_varejo'], model='additive', period=12)
#x13.x13_arima_analysis(endog = dados.empregados_no_varejo, freq = "M")
ajuste.observeddata
1995-01-01 13775.2
1995-02-01 13579.5
1995-03-01 13539.2
1995-04-01 13654.1
1995-05-01 13757.5
...
2019-05-01 15691.6
2019-06-01 15775.5
2019-07-01 15785.9
2019-08-01 15749.5
2019-09-01 15611.3
Name: empregados_no_varejo, Length: 297, dtype: float64
ajuste.seasonaldata
1995-01-01 -86.080304
1995-02-01 -280.313985
1995-03-01 -247.450443
1995-04-01 -185.463796
1995-05-01 -82.955644
...
2019-05-01 -82.955644
2019-06-01 -6.903832
2019-07-01 -11.089332
2019-08-01 -10.104262
2019-09-01 -97.809297
Name: seasonal, Length: 297, dtype: float64
import matplotlib.pyplot as plt
import matplotlib.dates as mdates
plt.rcParams.update({'figure.figsize': (16,12)})
ajuste.plot().suptitle('Decomposição Aditiva', fontsize=16)
plt.tight_layout(rect=[0, 0.03, 1, 0.95])
plt.show()# Visualização de dados
(
dados
.assign(ajuste = ajuste.observed-ajuste.seasonal)
.plot(title = "Empregados no Varejo (BSL/US)", xlabel = "", figsize = (10, 5))
.legend(["Série sazonal", "Série dessazonalizada"])
)Notas de rodapé
Todo este material foi retirado de diversas postagens e cursos da Análise Macro (www.analisemacro.com.br)↩︎